/*
 * Copyright 2010, 2011 Matt Oliveri
 *
 * This file is part of JConfigGen
 *
 * JConfigGen is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * JConfigGen is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with JConfigGen.  If not, see <http://www.gnu.org/licenses/>.
 */

package atma.jconfiggen;

import java.io.PrintStream;

/** Evaluate an expression in a code block.
 * <p>
 * This expression type nests its subexpression in a code block.
 * See the <a href="package-summary.html">package description</a> for an explanation of block scope.
 * The evaluation and result of a {@code Block} are the same as those of the {@code Block}'s subexpression.
 * </p>
 * <p>
 * A {@code Block} expression can also optionally be given an id.
 * Since the {@code Block} expression itself is considered to be outside the block it introduces, this id allows you to usefully bind the result to a name.
 * (Giving the subexpression an id would be pretty useless, since the name would immediately go out of scope.)
 * </p>
 */
public final class Block extends IdExpr
{
	private final Expr exp;

	/** Construct a {@code Block}.
	 * @param c The {@link Config} that will contain this expression.
	 * @param i The id to assign to this expression, or null.
	 * @param e The subexpression.
	 */
	public Block(Config c,String i,Expr e)
	{
		super(c,i);
		exp = e;
	}

	void printType(PrintStream out) throws InvalidConfigException {exp.printType(out);}
	boolean hasStats() {return true;}

	void printStats(PrintStream out,int tabs) throws InvalidConfigException
	{
		// An exception to the normal rule of statize() being called at most once.
		// We know it's safe this time though, given the implementation.
		statize();
		boolean skipAssign;
		if (id == none)
		{
			exp.discard();
			skipAssign = true;
		}
		else
		{
			if (!oldId)
			{
				pTabs(out,tabs);
				printDecl(out);
				out.println(';');
			}
			skipAssign = exp.useId(id);
		}
		pTabs(out,tabs);
		out.println('{');
		exp.printStats(out,tabs + 1);
		if (!skipAssign)
		{
			pTabs(out,tabs + 1);
			out.print(id);
			out.print(" = ");
			exp.printExpr(out);
			out.println(';');
		}
		pTabs(out,tabs);
		out.println('}');
	}

	void printExpr(PrintStream out) {out.print(id);}
}
